package priv.dajie.tzzq.bot.steam;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import priv.dajie.tzzq.bot.exception.BuyException;
import priv.dajie.tzzq.bot.exception.NetworkException;
import priv.dajie.tzzq.bot.exception.TradeException;
import priv.dajie.tzzq.bot.steam.exception.SteamGetMinPriceException;
import priv.dajie.tzzq.bot.steam.exception.SteamNeedLoginException;
import priv.dajie.tzzq.model.GoodsState;
import priv.dajie.tzzq.bot.model.*;
import priv.dajie.tzzq.common.Retryer;
import priv.dajie.tzzq.common.SteamPrice;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SteamBot {

    private SteamUser steamUser;
    private Logger logger = LogManager.getLogger(this.getClass());

    private Pattern pricePattern = Pattern.compile("[0-9]{1,3}(,[0-9]{3})*(\\.[0-9]{1,2})*");
    private Pattern tradeTimePattern = Pattern.compile("[A-Z][a-z]{2} [A-Z][a-z]{2} {1,2}[0-9]{1,2} [0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{4}");
    private Pattern partnerPattern = Pattern.compile("profiles/(.*)");
    private Pattern steamNamePattern = Pattern.compile("market_hash_name\":\"(.*)\",\"market_name");

    public SteamBot(SteamUser steamUser) {
        this.steamUser = steamUser;
        if (!steamUser.isLogin()) {
            throw new SteamNeedLoginException();
        }
    }

    public SteamUser getSteamUser() {
        return steamUser;
    }

    public BigDecimal getMinFeePrice(String nameid) {
        return SteamPrice.feePrice(getMinPrice(nameid));
    }

    public PriceNum[] getMinPrices(String nameID) {
        try {
            URIBuilder uriBuilder = new URIBuilder("https://steamcommunity.com/market/itemordershistogram");
            uriBuilder.setParameter("country", "CN");
            uriBuilder.setParameter("language", "schinese");
            uriBuilder.setParameter("currency", "23");
            uriBuilder.setParameter("item_nameid", nameID);
            uriBuilder.setParameter("two_factor", "0");
            uriBuilder.setParameter("norender", "1");
            HttpGet httpGet = new HttpGet(uriBuilder.build());

            int i = 0;
            int error = 0;
            while (true) {
                String html;
                try {
                    html = steamUser.open(httpGet, true);
                } catch (NetworkException e) {
                    logger.error(e);
                    try {
                        Thread.sleep(1000*++i);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    continue;
                }
                JSONObject jsonObject;
                try {
                    jsonObject = JSON.parseObject(html);
                } catch (Exception e) {
                    logger.error("获取销售价格失败：" + httpGet);
                    return null;
                }
                if(jsonObject==null){
                    try {
                        logger.error("获取最低价失败返回数据为空："+httpGet);
                        if(error++ > 5){
                            return null;
                        }
                        else if(error>2){
                            steamUser.changeProxy();
                        }
                        Thread.sleep(5000*error);
                        continue;
                    } catch (InterruptedException e) {
                        logger.error(e);

                    }
                }

                if (jsonObject.getBoolean("success")!=null && jsonObject.getBoolean("success")) {
//                    String prefix = jsonObject.getString("price_prefix");
                    JSONArray sellOrders = jsonObject.getJSONArray("sell_order_table");
                    if (sellOrders == null) {
                        logger.error("获取销售价格失败：" + httpGet);
                        return null;
                    }
                    PriceNum[] priceNums = new PriceNum[sellOrders.size()];
                    for (int j = 0; j < sellOrders.size(); j++) {
                        JSONObject sellOrder = sellOrders.getJSONObject(j);
                        String priceStr = sellOrder.getString("price");
                        Matcher matcher = pricePattern.matcher(priceStr);
                        if (matcher.find()) {
                            priceStr = matcher.group(0).replace(",", "");
                        }
                        BigDecimal price = new BigDecimal(priceStr);
                        int num = sellOrder.getInteger("quantity");
                        priceNums[j] = new PriceNum(price, num);
                    }
                    return priceNums;
                } else {
                    if (i > 3) {
                        throw new SteamGetMinPriceException("网页无法返回最低价");
                    }
                    try {
                        Thread.sleep(5000 * i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return null;
    }

    public BigDecimal getMinPrice(String nameID) { // 通过steam_info数据库查询对应的nameid 查询最低价。
        PriceNum[] priceNums = getMinPrices(nameID);
        if (priceNums == null) {
            return new BigDecimal("0");
        }
        return priceNums[0].getPrice();
    }

    public List<SteamSellItem> getSellList(String steamName) { // 获取商品销售价格列表，不可以多次调用
        List<SteamSellItem> ls = new ArrayList<>();
        List<NameValuePair> data = new ArrayList<>();
        try {
            // 添加请求参数
            data.add(new BasicNameValuePair("start", "0"));
            data.add(new BasicNameValuePair("count", "10"));
            data.add(new BasicNameValuePair("country", "CN"));
            data.add(new BasicNameValuePair("language", "schinese"));
            data.add(new BasicNameValuePair("currency", "23"));
            URIBuilder uriBuilder = new URIBuilder("https://steamcommunity.com/market/listings/570/" + steamName.replace(" ", "%20") + "/render/");
            uriBuilder.addParameters(data);
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            //提交请求
            String jsonText = steamUser.open(httpGet, true);

            JSONObject json = JSONObject.parseObject(jsonText);

            if (json.getBoolean("success")) {
                // 获取json中返回的html代码
                String html = json.getString("results_html");
                Document document = Jsoup.parse(html);
                Elements divs = document.select("div.market_listing_row.market_recent_listing_row");
                JSONObject listinginfo;
                try {
                    listinginfo = json.getJSONObject("listinginfo");
                } catch (ClassCastException e) {
                    return ls;
                }
                // 分析每一个div，并获取SteamSellingItem的参数
                for (Element div : divs) {
                    String idHref = div.attr("id");
                    String listingid = idHref.replaceFirst("listing_", "");
                    JSONObject item = listinginfo.getJSONObject(listingid);
                    BigDecimal price = new BigDecimal(div.select("span.market_listing_price.market_listing_price_with_fee").first().text().replace("¥ ", ""));
                    int subtotal = item.getInteger("converted_price");
                    int fee = item.getInteger("converted_fee");
                    SteamSellItem sellingItem = new SteamSellItem(steamName, listingid, price, subtotal, fee);
                    ls.add(sellingItem);
                }
            }
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return ls;
    }

    // 需通过getSellingList获取SteamSellingItem
    public void buy(SteamSellItem steamSellItem) throws BuyException {
        try {
            HttpPost httpPost = new HttpPost("https://steamcommunity.com/market/buylisting/" + steamSellItem.getListingid());
            // 设置请求参数
            List<NameValuePair> data = new ArrayList<>();
            data.add(new BasicNameValuePair("sessionid", steamUser.getSessionID()));
            data.add(new BasicNameValuePair("currency", "23"));
            data.add(new BasicNameValuePair("subtotal", String.valueOf(steamSellItem.getSubtotal())));
            data.add(new BasicNameValuePair("fee", String.valueOf(steamSellItem.getFee())));
            data.add(new BasicNameValuePair("total", String.valueOf(steamSellItem.getSubtotal() + steamSellItem.getFee())));
            data.add(new BasicNameValuePair("quantity", "1"));
            httpPost.setEntity(new UrlEncodedFormEntity(data));
            httpPost.setHeader(steamUser.getHeaderCookies());
            httpPost.setHeader(new BasicHeader("Referer", "https://steamcommunity.com/market/listings/570/Heavenly%20Guardian%20Quiver"));
            String jsonText = steamUser.open(httpPost, true);
            JSONObject json = JSON.parseObject(jsonText);
            System.out.println(jsonText);
            if (json.getJSONObject("wallet_info").getInteger("success") != 1) {
                throw new BuyException("购买失败 ", json);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    public SteamPackItems getPack() {
        SteamPackItems steamPackItems = new SteamPackItems();
        try {
            URIBuilder uriBuilder = new URIBuilder("https://steamcommunity.com/inventory/" + steamUser.getSteamId() + "/570/2");
            uriBuilder.addParameter("l", "schinese");
            uriBuilder.addParameter("count", "3000");
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            String jsonText = steamUser.open(httpGet, true);
//            System.out.println(jsonText);
            JSONObject json = JSON.parseObject(jsonText);
            Integer count = json.getInteger("total_inventory_count");
            if (count == null || json.getInteger("success") != 1) {
                throw new NetworkException("库存获取失败"+json);
            }
            JSONArray assets = json.getJSONArray("assets");
            JSONArray descriptions = json.getJSONArray("descriptions");
            int num = 0;
            for (int i = 0; i < descriptions.size(); i++) { // 遍历返回的数据(assets与descriptions)
                JSONObject description = descriptions.getJSONObject(i);
                String steamName = description.getString("market_hash_name");
                String classid = description.getString("classid");
                while (!assets.getJSONObject(num).getString("classid").equals(classid)) {
                    num++;
                }
                String assetid = assets.getJSONObject(num).getString("assetid");
                Date tradeTime = null;
                JSONArray ownerDescriptions = description.getJSONArray("owner_descriptions");
                // 获取商品开放交易的时间
                if (description.getInteger("tradable") == 0) {
                    if (ownerDescriptions != null) {
                        String tradeTimeStr = ownerDescriptions.getJSONObject(0).getString("value");
                        Matcher matcher = tradeTimePattern.matcher(tradeTimeStr);
                        if (matcher.find()) {
                            tradeTimeStr = matcher.group(0);
                        }
                        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US);
                        tradeTime = sdf.parse(tradeTimeStr);
                    } else {
                        continue;
                    }
                }
                steamPackItems.add(new SteamPackItem(steamName, assetid, tradeTime));
            }
        } catch (URISyntaxException | ParseException e) {
            e.printStackTrace();
        }
        return steamPackItems;
    }

    private String getPartner(String tradeid) throws TradeException {
        int i = 1;
        while (true) {
            HttpGet tradeURL = new HttpGet("https://steamcommunity.com/tradeoffer/" + tradeid);
//        System.out.println(tradeURL);
            String html = steamUser.open(tradeURL, true);
            Document document = Jsoup.parse(html);
            Element errorMsg = document.selectFirst("div#error_msg");
            if (errorMsg != null) {
                throw new TradeException(errorMsg.text());
            }
            // 获取parterID

            Element partnerSpan = document.selectFirst("span.trade_partner_headline_sub");
            if (partnerSpan == null) {
                try {
                    Thread.sleep(3000 * i++);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    if (i > 3) {
                        throw new TradeException(e);
                    }
                }
                continue;
            }
            Element a = partnerSpan.selectFirst("a");
            String partnerURL = a.attr("href");


            Matcher matcher = partnerPattern.matcher(partnerURL);
            String partner = "";
            if (matcher.find()) {
                partner = matcher.group(1);
            }
            return partner;
        }
    }

    // 用于发货的交易
    public boolean deliverTrade(String tradeid) throws TradeException{
        JSONObject json =  acceptTrade(tradeid);
        if(json!=null&&json.getBoolean("needs_mobile_confirmation") != null){
            return json.getBoolean("needs_mobile_confirmation");
        }
        return false;
    }

    public String trade(String tradeid) throws TradeException {
        JSONObject json = acceptTrade(tradeid);
        String successID = json.getString("tradeid");
        if(successID == null){
            logger.error("steam交易返回数据异常："+json);
        }

        logger.info("交易成功交易单号:" + successID);
        return successID;
    }

    private JSONObject acceptTrade(String tradeid) {
        final String[] partner = new String[1];
        logger.info("交易" + tradeid + "：获取对方steamID");
        try { // 自动重试
            Retryer.retry(() -> partner[0] = getPartner(tradeid), 10);
        } catch (Exception e) {
            logger.error(e);
            return null;
        }
        return acceptTrade(tradeid, partner[0]);
    }

    private JSONObject acceptTrade(String tradeid, String partner) {
        String sessionID = steamUser.getCookiesByName("sessionid");
        HttpPost httpPost = new HttpPost("https://steamcommunity.com/tradeoffer/" + tradeid + "/accept");
        // 设置header
        Header[] headers = new Header[2];
        headers[0] = new BasicHeader("Referer", "https://steamcommunity.com/tradeoffer/" + tradeid + "/");
        headers[1] = steamUser.getHeaderCookies();
        httpPost.setHeaders(headers);
        // 设置参数
        List<NameValuePair> data = new ArrayList<>();
        data.add(new BasicNameValuePair("sessionid", sessionID));
        data.add(new BasicNameValuePair("serverid", "1"));
        data.add(new BasicNameValuePair("tradeofferid", tradeid));
        data.add(new BasicNameValuePair("partner", partner));
        data.add(new BasicNameValuePair("captcha", ""));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(data));
        } catch (UnsupportedEncodingException e) {
            throw new NetworkException(e.getMessage());
        }
        String jsonStr;
        int error = 0;
        while (true) {
            try {
                jsonStr = steamUser.open(httpPost, true); // 提交接收请求
                break;
            } catch (NetworkException e) {
                logger.error(e);
                try {
                    Thread.sleep(1000 * ++error);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                if (error > 3) {
                    throw e;
                }
            }
        }
        JSONObject json = JSONObject.parseObject(jsonStr);
        return json;

    }

    public List<String> getTradeItems(String tradeid) {

        HttpGet httpGet = new HttpGet("https://steamcommunity.com/trade/" + tradeid + "/receipt");
        String html;
        int error = 0;
        while (true) {
            try {
                html = steamUser.open(httpGet, true);
                break;
            } catch (NetworkException e) {
                logger.error("获取交易物品失败第" + error + "次：" + e);
                try {
                    Thread.sleep(1000 * error);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        Matcher matcher = steamNamePattern.matcher(html);
        List<String> steamNames = new ArrayList<>();
        while (matcher.find()) {
            steamNames.add(matcher.group(1));
        }
        return steamNames;
    }

    public HistoryPrices getHistoryPrices(String steamName) {


        HistoryPrices historyPrices = new HistoryPrices();
        HttpGet httpGet = new HttpGet("https://steamcommunity.com/market/pricehistory?appid=570&market_hash_name=" + steamName.replace(" ", "%20"));
        String jsonStr = steamUser.open(httpGet, true);
        JSONObject json = JSON.parseObject(jsonStr);
        if (json == null || !json.getBoolean("success")) {
            throw new NetworkException("历史交易记录获取失败");
        }
        JSONArray prices = json.getJSONArray("prices");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MMM dd yyyy HH: +0", Locale.ENGLISH);
        for (int i = 0; i < prices.size(); i++) {
            JSONArray priceItem = prices.getJSONArray(i);
            String dateStr = priceItem.getString(0);
            Date date = null;
            try {
                date = simpleDateFormat.parse(dateStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            BigDecimal price = priceItem.getBigDecimal(1);
            int num = priceItem.getInteger(2);
            historyPrices.add(new HistoryPrice(date, price, num));
        }
        return historyPrices;

    }

    public SteamSellState sell(SteamPackItem steamPackItem, BigDecimal sPrice) {
        int sellPrice = (int) (sPrice.doubleValue() * 100);
        HttpPost httpPost = new HttpPost("https://steamcommunity.com/market/sellitem/");
        List<NameValuePair> data = new ArrayList<>();
        data.add(new BasicNameValuePair("sessionid", steamUser.getSessionID()));
        data.add(new BasicNameValuePair("appid", "570"));
        data.add(new BasicNameValuePair("contextid", "2"));
        data.add(new BasicNameValuePair("assetid", steamPackItem.getAssetid()));
        data.add(new BasicNameValuePair("amount", "1"));
        data.add(new BasicNameValuePair("price", sellPrice + ""));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(data));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Header[] headers = new Header[2];
        headers[0] = new BasicHeader("Referer", "https://steamcommunity.com/profiles/" + steamUser.getSteamId() + "/inventory?modal=1&market=1");
        headers[1] = steamUser.getHeaderCookies();
        httpPost.setHeaders(headers);
        String jsonStr;
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(25000)
                .setConnectionRequestTimeout(25000).setSocketTimeout(25000)
                .build();
        httpPost.setConfig(requestConfig);
        int error = 1;
        while (true) {
            try {
                jsonStr = steamUser.open(httpPost, true);
                break;
            } catch (NetworkException e) {
                logger.error("提交出售请求失败第" + error + "次：" + e);
                try {
                    Thread.sleep(3000 * error++);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        JSONObject json = JSON.parseObject(jsonStr);
        // 没有出售成功
        if (!json.getBoolean("success")) {
            logger.error("商品上架失败：" + json);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for (SteamSellingItem steamSellingItem : getConfirmItems()) {
                if (steamSellingItem.getSteamName().equals(steamPackItem.getSteamName())) {
                    unsell(steamSellingItem);
                    logger.info("下架商品："+steamSellingItem.getSteamName());
                    break;
                }
            }

            return new SteamSellState(GoodsState.PACKAGE, null);
        }
        // 待确认
        if (json.getInteger("requires_confirmation") == 1 && json.getBoolean("needs_mobile_confirmation")) {
            // 待确认 3种可能 1.在确认列表中 2.立刻被确认 商品在出售列表中 3.立刻被确认且立即被购买 商品在历史交易记录中
            return new SteamSellState(GoodsState.CONFIRMING, getSellID(steamPackItem.getSteamName(), GoodsState.CONFIRMING));
        }
        // 待出售
        else
        {
            return new SteamSellState(GoodsState.SELLING, getSellID(steamPackItem.getSteamName(), GoodsState.SELLING));
        }
    }

    private String getSellID(String steamName, GoodsState sState) {
        for (int x = 0; x < 3; x++) {
            if (sState == GoodsState.CONFIRMING) {
                // 搜索确认记录
                for (SteamSellingItem steamSellingItem : getConfirmItems()) {
                    if (steamSellingItem.getSteamName().equals(steamName)) {
                        return steamSellingItem.getListingid();
                    }
                }
            }
            List<SteamSellingItem> lastSellingItems = getLastSellingItems(50);
            // 从尾部开始搜索在售记录
            for (int i = lastSellingItems.size() - 1; i >= 0; i--) {
                if (lastSellingItems.get(i).getSteamName().equals(steamName)) {
                    return lastSellingItems.get(i).getListingid();
                }
            }
            // 搜索出售记录
            for (SteamTradeHistory steamTradeHistory : getTradeHistoryByCount(100))
            {
                if (steamTradeHistory.getSteamName().equals(steamName)) {
                    return steamTradeHistory.getListingid();
                }
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        throw new RuntimeException("上架商品id搜索失败");
    }


    public List<SteamSellingItem> getLastSellingItems(int num) {
        if (num > 100) {
            throw new RuntimeException("搜索数量暂不支持大于100");
        }
        // 当前在售商品的数量
        String jsonStr = steamUser.open(new HttpGet("https://steamcommunity.com/market/mylistings/render/?query=&start=0&count=1&norender=1"), true);
        JSONObject json = JSON.parseObject(jsonStr);
        int max = json.getInteger("total_count");
        int start = Math.max((max - num - 1), 0);
        // 获取倒数num个在售商品
        jsonStr = steamUser.open(new HttpGet("https://steamcommunity.com/market/mylistings/render/?query=&start=" + start + "&count=" + num + "&norender=1"), true);
        json = JSON.parseObject(jsonStr);
//        System.out.println(jsonStr);
        return parseSellingJSON(json.getJSONArray("listings"), GoodsState.SELLING);
    }

    private SteamSellingItems parseSellingJSON(JSONArray json, GoodsState goodsState) {
        SteamSellingItems steamSellingItems = new SteamSellingItems();
        if(json==null){
            return steamSellingItems;
        }

        for (int i = 0; i < json.size(); i++) {
            JSONObject item = json.getJSONObject(i);
            String listingid = item.getString("listingid");
            BigDecimal price = item.getBigDecimal("price").divide(new BigDecimal("100"));
            String steamName = item.getJSONObject("asset").getString("market_hash_name");
            steamSellingItems.add(new SteamSellingItem(steamName, price, listingid, goodsState));
        }
        return steamSellingItems;
    }

    public SteamSellingItems getSellingItems() {
        int max = 0;
        int start = 0;
        int count = 100;
        SteamSellingItems steamSellingItems = new SteamSellingItems();
        do {
            HttpGet httpGet = new HttpGet("https://steamcommunity.com/market/mylistings/render/?query=&start=" + start + "&count=" + count + "&norender=1");
            String jsonStr = steamUser.open(httpGet, true);
//            System.out.println(httpGet);
//           System.out.println(jsonStr);


            // 部分饰品会导致返回数据异常，原因不明？？
            JSONObject json = JSON.parseObject(jsonStr);
            Boolean success = json.getBoolean("success");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            JSONArray sellingItems = json.getJSONArray("listings");
            int error = 1;
            if (success == null || !success) {
                logger.error("获取在售商品失败，" + 5 * ++error + "秒后重试:" + httpGet);
                try {
                    Thread.sleep(5000 * error);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                continue;
            } else if (sellingItems == null) { // 防止在获取销售记录过程中max<start，造成空指针异常
                break;
            }
            List<SteamSellingItem> temp = parseSellingJSON(sellingItems, GoodsState.SELLING);
            max = json.getInteger("total_count");
            steamSellingItems.addAll(temp);
            start += count;
        } while (max > start);
        return steamSellingItems;
    }

    public SteamSellingItems getConfirmItems() {
        int start = 0;
        int count = 100;
        String jsonStr = steamUser.open(new HttpGet("https://steamcommunity.com/market/mylistings/render/?query=&start=" + start + "&count=" + count + "&norender=1"), true);
        JSONObject json = JSON.parseObject(jsonStr);
        JSONArray sellingItems = json.getJSONArray("listings_to_confirm");
        return parseSellingJSON(sellingItems, GoodsState.CONFIRMING);
    }

    public SteamTradeHistorys getTradeHistory(int maxPage) {
        return getTradeHistory(maxPage, -1, 500);
    }

    public SteamTradeHistorys getTradeHistoryByCount(int count) {
        return getTradeHistory(1, -1, count);
    }

    public SteamTradeHistorys getTradeHistoryByTime(long stimeMax) {
        return getTradeHistory(-1, stimeMax, 500);
    }

    private SteamTradeHistorys getTradeHistory(int maxPage, long stimeMax, int count) {
        SteamTradeHistorys steamTradeHistories = new SteamTradeHistorys();
        int start = 0;
        int max = 10;
        int page = 0;
        if (stimeMax > 0) {
            stimeMax += 60 * 60 * 2 * (long) 1000;
        }
        r:
        do {
            final String[] jsonStr = new String[1];
            int finalStart = start;
            try {
                Retryer.retry(() -> jsonStr[0] = steamUser.open(new HttpGet("https://steamcommunity.com/market/myhistory?norender=1&count=" + count + "&start=" + finalStart), true));
            } catch (Exception e) {
                e.printStackTrace();
            }

            JSONObject json = JSON.parseObject(jsonStr[0]);
            JSONArray events;
            JSONObject listings;
            JSONObject assets;
            if (!json.getBoolean("success")) {
                logger.error("获取交易记录失败");
                continue;
            }
            if (json.getInteger("total_count") == null) {
                System.out.println(json);
                continue;
            }
            max = json.getInteger("total_count");
            try {
                events = json.getJSONArray("events");
                listings = json.getJSONObject("listings");
                assets = json.getJSONObject("assets").getJSONObject("570").getJSONObject("2");
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
                continue;
            }
            for (int i = 0; i < events.size(); i++) {
                long time = events.getJSONObject(i).getLong("time_event") * 1000;
                long stime = System.currentTimeMillis() - time;
//                System.out.println(stime);
//                System.out.println(stimeMax);
                if (stimeMax > 0 && stime > stimeMax) {
                    break r;
                }
                Date date = new Date(time);
                int eventType = events.getJSONObject(i).getInteger("event_type");
                GoodsState goodsState;
                switch (eventType) {
                    case 1:
                        goodsState = GoodsState.SELLING;
                        break;
                    case 2:
                        goodsState = GoodsState.PACKAGE;
                        break;
                    case 3:
                        goodsState = GoodsState.SUCCESS;
                        break;
                    case 4:
                        goodsState = GoodsState.BUY;
                        break;
                    default:
                        goodsState = GoodsState.UNKNOWN;
                }
                String listingid = events.getJSONObject(i).getString("listingid");
                String id = listings.getJSONObject(listingid).getJSONObject("asset").getString("id");
                if (assets.getJSONObject(id)== null)
                    continue ;

                String steamName = assets.getJSONObject(id).getString("market_hash_name");

                steamTradeHistories.add(new SteamTradeHistory(steamName, listingid, date, goodsState));
            }
            start += count;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } while (start < max && (maxPage <= 0 || ++page < maxPage));
        return steamTradeHistories;
    }

    public boolean unsell(SteamSellingItem steamSellingItem) {
        return unsell(steamSellingItem.getListingid());
    }

    public boolean unsell(String listingid) {
        HttpPost httpPost = new HttpPost("https://steamcommunity.com/market/removelisting/" + listingid);
        httpPost.setHeader(steamUser.getHeaderCookies());
        httpPost.setHeader(new BasicHeader("Referer", "https://steamcommunity.com/market/"));
        List<NameValuePair> data = new ArrayList<>();
        data.add(new BasicNameValuePair("sessionid", steamUser.getSessionID()));
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(data));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String jsonStr;
        int error = 0;
        while (true) {
            try {
                jsonStr = steamUser.open(httpPost, true);
                break;
            }catch (NetworkException e){
                logger.error(e);
                if (error>3) {
                    throw  e;
                }
                try {
                    Thread.sleep(1000 * ++error);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

            }
        }
        if ("[]".equals(jsonStr)) {
            return true;
        }
        logger.error("下架商品失败：" + jsonStr);
        return false;
    }

}
